<template>
  <div class="calligraphy-container">
    <el-row 
      :gutter="25" 
      class="full-height"
      v-loading="fullscreenLoading"
      element-loading-text="正在识别中...（图片越大识别时间越长，如您图片较大，请耐心等待）"
      element-loading-background="rgba(255, 255, 255, 0.8)"
    >
      <el-col :span="11" class="left-panel">
        <div class="panel-content image-panel">
          <div class="image-wrapper">
            <el-image
              ref="imageRef"
              :src="getImageSrc"
              fit="contain"
              class="calligraphy-image"
              @load="sendToOCR"
            />
            <svg 
              v-if="multipleHighlights.length > 0 || activeHighlight"
              class="highlight-overlay"
              :viewBox="`0 0 ${imageInfo.naturalWidth * getScaleFactor} ${imageInfo.naturalHeight * getScaleFactor}`"
              :style="svgStyle"
            >
              <polygon
                v-for="(highlight, index) in multipleHighlights"
                :key="`search-${index}`"
                :points="getPolygonPoints(highlight)"
                fill="rgba(255, 0, 0, 0.2)"
                stroke="rgba(255, 0, 0, 0.5)"
                stroke-width="2"
              />
              <polygon
                v-if="activeHighlight"
                :points="getPolygonPoints(activeHighlight)"
                fill="rgba(255, 0, 0, 0.2)"
                stroke="rgba(255, 0, 0, 0.5)"
                stroke-width="2"
              />
            </svg>
          </div>
        </div>
      </el-col>
      <el-col :span="7" class="middle-panel">
        <div class="panel-content scrollable">
          <div class="search-bar">
            <el-input
              v-model="searchText"
              placeholder="请输入单字"
              class="search-input"
              clearable
              @clear="clearHighlight"
            >
              <template #suffix>
                <el-icon><Search /></el-icon>
              </template>
            </el-input>
          </div>
          <div class="result-header">识别结果</div>
          <div class="ocr-results">
            <div 
              v-for="(text, index) in textResults" 
              :key="index" 
              class="result-item"
              @mouseenter="highlightText(index)"
              @mouseleave="clearHighlight"
            >
              {{ text }}
            </div>
          </div>
        </div>
      </el-col>
      <el-col :span="6" class="right-panel" style="background-color: #f3f5fa;">
        <div class="panel-content scrollable">
          <div 
            v-for="(item, index) in characterList" 
            :key="index" 
            class="character-item"
            @mouseenter="highlightCharacter(item)"
            @mouseleave="clearHighlight"
          >
            <div class="character-content">
              <span class="character-label">{{ item.text }}</span>
              <div 
                class="character-box-wrapper" 
                @click="handleCharacterClick(item)"
              >
                <div 
                  class="character-box"
                  :style="{
                    backgroundImage: `url(${getImageSrc})`,
                    backgroundPosition: `${-item.position[0]}px ${-item.position[1]}px`,
                    width: `${item.position[2] - item.position[0]}px`,
                    height: `${item.position[3] - item.position[1]}px`,
                    transform: `scale(${80 / Math.max(item.position[2] - item.position[0], item.position[3] - item.position[1])})`,
                  }"
                ></div>
              </div>
              <div class="modify-options">
                <div 
                  v-for="(_, choiceIndex) in 2" 
                  :key="choiceIndex" 
                  class="choice-box clickable"
                  @click.stop="handleChoiceClick(item, choiceIndex)"
                >
                  {{ getChoiceCharacters(item.choices)[choiceIndex] }}
                </div>
                <div 
                  v-if="item.customChoice" 
                  class="choice-box clickable"
                  @click.stop="handleCustomChoice(item)"
                >
                  {{ item.customChoice }}
                </div>
                <el-input
                  v-else
                  v-model="item.customChoice"
                  class="choice-box"
                  maxlength="1"
                  placeholder=""
                  @click.stop
                />
              </div>
            </div>
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script lang="ts" setup>
import { ref, computed, nextTick, watch, onMounted, onUnmounted } from 'vue'
import { useImageStore } from '@/stores/imageStore'
import { storeToRefs } from 'pinia'
import axios from 'axios'
import { Search } from '@element-plus/icons-vue'
import fanImage from '@/assets/fan.png'
import type { ElImage } from 'element-plus'
import { useRouter } from 'vue-router'

const imageStore = useImageStore()
const { selectedImage, textDirection } = storeToRefs(imageStore)
const searchText = ref('')
const ocrResult = ref('')

interface WordInfo {
  choices: string;
  confidence: number;
  det_confidence: number;
  position: number[];
  text: string;
}

interface CharacterInfo {
  text: string;
  position: number[];
  boundingBox?: [number, number][];
  choices?: string;
  customChoice?: string;
  originalData?: WordInfo;
}

const characterList = ref<CharacterInfo[]>([])
const activeHighlight = ref<[number, number][] | null>(null)

const getImageSrc = computed(() => {
  return selectedImage.value || ''
})

const ocrApiUrl = 'https://ocr.kandianguji.com/ocr_api'
const token = '35a41b75-deea-4ee4-b06e-5b1a6c74a0b9'
const email = '1473763052@qq.com'

const textResults = ref<string[]>([])

const imageRef = ref<InstanceType<typeof ElImage> | null>(null)
const imageInfo = ref({
  naturalWidth: 0,
  naturalHeight: 0
})

interface TextLine {
  text: string;
  position: [number, number][];
  words: WordInfo[];
}

// 添加新的 ref 来存储文本行信息
const textLines = ref<TextLine[]>([])

// 更新图片信���
const updateImageInfo = () => {
  const imgElement = document.querySelector('.calligraphy-image img') as HTMLImageElement
  if (!imgElement) return

  const { naturalWidth, naturalHeight } = imgElement
  imageInfo.value = {
    naturalWidth,
    naturalHeight
  }
}

// 添加图片缩放比例计算
const getScaleFactor = computed(() => {
  const imgElement = document.querySelector('.calligraphy-image img') as HTMLImageElement
  if (!imgElement) return 1

  // 获取图片实际显示尺寸
  const displayWidth = imgElement.clientWidth
  const displayHeight = imgElement.clientHeight

  // 计算缩放比例
  const scaleX = displayWidth / imageInfo.value.naturalWidth
  const scaleY = displayHeight / imageInfo.value.naturalHeight

  return Math.min(scaleX, scaleY)
})

// 修改坐标转换方法
const getPolygonPoints = (points: [number, number][]) => {
  const scale = getScaleFactor.value
  return points.map(point => {
    const scaledX = point[0] * scale
    const scaledY = point[1] * scale
    return `${scaledX},${scaledY}`
  }).join(' ')
}

// 添加 fullscreenLoading ref
const fullscreenLoading = ref(false)

// 修改 getDetMode 计算属性
const getDetMode = computed(() => {
  switch (textDirection.value) {
    case 'vertical':
      return 'sp'
    case 'horizontal':
      return 'hp'
    default:
      return 'auto'
  }
})

const sendToOCR = async (event: Event) => {
  const img = event.target as HTMLImageElement
  
  await nextTick()
  updateImageInfo()
  
  fullscreenLoading.value = true
  
  const canvas = document.createElement('canvas')
  canvas.width = img.naturalWidth
  canvas.height = img.naturalHeight

  const ctx = canvas.getContext('2d')
  if (!ctx) {
    console.error('无法获取canvas上下文')
    return
  }
  
  // 使用高质量的图片缩放
  ctx.imageSmoothingEnabled = true
  ctx.imageSmoothingQuality = 'high'
  ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight)

  const dataURL = canvas.toDataURL('image/png')
  const base64Image = dataURL.split(',')[1]

  try {
    const response = await axios.post(ocrApiUrl, {
      token,
      email,
      image: base64Image,
      det_mode: getDetMode.value,  // 使用计算属性的值
      char_ocr: false,
      image_size: 0,
      return_position: true,
      return_choices: true
    })
    
    console.log('OCR API 响应结果:', response.data)
    
    ocrResult.value = response.data
    
    if (response.data.data && response.data.data.text_lines) {
      // 保存完整的文本行信息，包括words数组
      textLines.value = response.data.data.text_lines.map((line: any) => ({
        text: line.text,
        position: [
          [line.position[0][0], line.position[0][1]],
          [line.position[1][0], line.position[1][1]],
          [line.position[2][0], line.position[2][1]],
          [line.position[3][0], line.position[3][1]]
        ],
        words: line.words
      }))
      
      const characters: CharacterInfo[] = []
      response.data.data.text_lines.forEach((line: any) => {
        line.words.forEach((word: any) => {
          const boundingBox: [number, number][] = [
            [word.position[0], word.position[1]],
            [word.position[0], word.position[3]],
            [word.position[2], word.position[3]],
            [word.position[2], word.position[1]]
          ]
          
          characters.push({
            text: word.text,
            position: word.position,
            boundingBox,
            choices: word.choices,
            originalData: { ...word }
          })
        })
      })
      characterList.value = characters
    }

    if (response.data.data && response.data.data.texts) {
      textResults.value = response.data.data.texts
    }
  } catch (error) {
    console.error('Error sending image to OCR:', error)
  } finally {
    fullscreenLoading.value = false
  }
}

// 监听窗口大小变化
onMounted(() => {
  window.addEventListener('resize', updateImageInfo)
})

onUnmounted(() => {
  window.removeEventListener('resize', updateImageInfo)
})

// 监听图片变化
watch(getImageSrc, () => {
  nextTick(updateImageInfo)
})

// 添加文本行高亮方法
const highlightText = (index: number) => {
  if (textLines.value[index]) {
    activeHighlight.value = textLines.value[index].position
  }
}

// 修改字符高亮方法名称以区分
const highlightCharacter = (character: CharacterInfo) => {
  if (character.boundingBox) {
    activeHighlight.value = character.boundingBox
  }
}

const clearHighlight = () => {
  activeHighlight.value = null
}

// 添加一个新的 ref 来存储多个高亮区域
const multipleHighlights = ref<[number, number][][]>([])

// 修改搜索相关的方法
const searchContent = () => {
  if (!searchText.value) {
    multipleHighlights.value = []
    activeHighlight.value = null
    return
  }

  // 在 characterList 中查找所有匹配的字符
  const matchedChars = characterList.value.filter(char => char.text === searchText.value)
  
  if (matchedChars.length > 0) {
    // 收集所有匹配字符的边界框
    const highlights = matchedChars
      .map(char => char.boundingBox)
      .filter((box): box is [number, number][] => box !== undefined)
    
    multipleHighlights.value = highlights
  } else {
    multipleHighlights.value = []
  }
}

// 修改 watch 以使用新的搜索方法
watch(searchText, () => {
  searchContent()
})

// 添加一个计候选字的方法
const getChoiceCharacters = (choices: string | undefined): string[] => {
  if (!choices) return ['一', '二'] // 默认值
  const chars = choices.split('')
  return [chars[1] || '一', chars[2] || '二'] // 返回第二、三个字符
}

// 修改处理选项点击的方法
const handleChoiceClick = (item: CharacterInfo, choiceIndex: number) => {
  if (!item.choices) return
  const chars = item.choices.split('')
  const newChar = chars[choiceIndex + 1]
  if (newChar && item.originalData) {
    // 更新字符
    item.text = newChar
    item.originalData.text = newChar

    // 更新对应行的文本
    const lineIndex = textLines.value.findIndex(line => 
      line.words.some(word => 
        word.position[0] === item.originalData?.position[0] &&
        word.position[1] === item.originalData?.position[1]
      )
    )

    if (lineIndex !== -1) {
      const line = textLines.value[lineIndex]
      const wordIndex = line.words.findIndex(word => 
        word.position[0] === item.originalData?.position[0] &&
        word.position[1] === item.originalData?.position[1]
      )

      if (wordIndex !== -1) {
        line.words[wordIndex].text = newChar
        // 重新构建行文本
        line.text = line.words.map(word => word.text).join('')
        // 更新文本结果数组
        textResults.value[lineIndex] = line.text
      }
    }

    console.log('更新后的数据:', {
      character: item.originalData,
      line: textLines.value[lineIndex],
      fullText: textResults.value[lineIndex]
    })
  }
}

// 同样修改自定义选项处理方法
const handleCustomChoice = (item: CharacterInfo) => {
  if (item.customChoice && item.originalData) {
    // 更新字符
    item.text = item.customChoice
    item.originalData.text = item.customChoice

    // 更新对应行的文本
    const lineIndex = textLines.value.findIndex(line => 
      line.words.some(word => 
        word.position[0] === item.originalData?.position[0] &&
        word.position[1] === item.originalData?.position[1]
      )
    )

    if (lineIndex !== -1) {
      const line = textLines.value[lineIndex]
      const wordIndex = line.words.findIndex(word => 
        word.position[0] === item.originalData?.position[0] &&
        word.position[1] === item.originalData?.position[1]
      )

      if (wordIndex !== -1) {
        line.words[wordIndex].text = item.customChoice
        // 重新构建行文本
        line.text = line.words.map(word => word.text).join('')
        // 更新文本结果数组
        textResults.value[lineIndex] = line.text
      }
    }

    console.log('更新后的数据:', {
      character: item.originalData,
      line: textLines.value[lineIndex],
      fullText: textResults.value[lineIndex]
    })
  }
}

// 修改 SVG overlay 的样式
const svgStyle = computed(() => {
  const imgElement = document.querySelector('.calligraphy-image img') as HTMLImageElement
  if (!imgElement) return {}

  return {
    position: 'absolute' as const,
    top: '0',
    left: '0',
    width: `${imgElement.clientWidth}px`,
    height: `${imgElement.clientHeight}px`,
    pointerEvents: 'none',
  }
})

// 添加对文本方向变化的监听
watch(textDirection, () => {
  const imgElement = document.querySelector('.calligraphy-image img') as HTMLImageElement
  if (imgElement) {
    sendToOCR({ target: imgElement } as unknown as Event)
  }
})

const router = useRouter()

// 添加处理点击字符卡片的方法
const handleCharacterClick = (item: CharacterInfo) => {
  // 获取后续字符
  const nextChars = getNextCharacters(item)
  
  // 创建一个新的 canvas 来裁剪字符图片
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  if (!ctx) return

  const img = document.querySelector('.calligraphy-image img') as HTMLImageElement
  if (!img) return

  // 设置 canvas 尺寸为字符区域大小
  const width = item.position[2] - item.position[0]
  const height = item.position[3] - item.position[1]
  canvas.width = width
  canvas.height = height

  // 裁剪字符区域
  ctx.drawImage(
    img,
    item.position[0],
    item.position[1],
    width,
    height,
    0,
    0,
    width,
    height
  )

  // 将裁剪后的图片转换为 base64
  const characterImage = canvas.toDataURL('image/png')

  // 裁剪后续字符的图片
  const nextCharImages = nextChars.map(char => {
    const nextCanvas = document.createElement('canvas')
    const nextCtx = nextCanvas.getContext('2d')
    if (!nextCtx) return null

    const nextWidth = char.position[2] - char.position[0]
    const nextHeight = char.position[3] - char.position[1]
    nextCanvas.width = nextWidth
    nextCanvas.height = nextHeight

    nextCtx.drawImage(
      img,
      char.position[0],
      char.position[1],
      nextWidth,
      nextHeight,
      0,
      0,
      nextWidth,
      nextHeight
    )

    return {
      character: char.text,
      image: nextCanvas.toDataURL('image/png')
    }
  })

  // 导航到字符展示页面，并传递主字符和后续字符的图片
  router.push({
    name: 'CharacterShow',
    params: { id: item.text },
    state: { 
      characterImage,
      nextCharacters: nextCharImages
    }
  })
}

// 添加状态持久化
onMounted(() => {
  // 如果有缓存的识别结果，恢复它们
  if (textResults.value.length === 0 && localStorage.getItem('ocrTextResults')) {
    textResults.value = JSON.parse(localStorage.getItem('ocrTextResults') || '[]')
    characterList.value = JSON.parse(localStorage.getItem('ocrCharacterList') || '[]')
    textLines.value = JSON.parse(localStorage.getItem('ocrTextLines') || '[]')
  }
})

// 在识别结果更新时保存状态
watch([textResults, characterList, textLines], () => {
  localStorage.setItem('ocrTextResults', JSON.stringify(textResults.value))
  localStorage.setItem('ocrCharacterList', JSON.stringify(characterList.value))
  localStorage.setItem('ocrTextLines', JSON.stringify(textLines.value))
}, { deep: true })

// 在组件卸载时清理状态
onUnmounted(() => {
  // 可以选择是否在这里清理localStorage
  // localStorage.removeItem('ocrTextResults')
  // localStorage.removeItem('ocrCharacterList')
  // localStorage.removeItem('ocrTextLines')
})

// 在 script setup 中添加新的方法和状态
const getNextCharacters = (currentChar: CharacterInfo): CharacterInfo[] => {
  const allChars = characterList.value
  const currentIndex = allChars.findIndex(char => 
    char.position[0] === currentChar.position[0] && 
    char.position[1] === currentChar.position[1]
  )
  
  if (currentIndex === -1) return []
  
  // 获取后面的6个字符
  return allChars.slice(currentIndex + 1, currentIndex + 7)
}
</script>

<style scoped>
.calligraphy-container {
  height: 70vh;
  margin-top: 15vh;
  padding: 20px;
  box-sizing: border-box;
  background-color: #f3f5fa;
}

.full-height {
  height: 100%;
}

.left-panel,
.middle-panel,
.right-panel {
  height: 100%;
}

.panel-content {
  background-color: #fff;
  border-radius: 4px;
  padding: 20px;
  height: 100%;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.search-bar {
  margin-bottom: 20px;
}

.search-input {
  width: 100%;
}

.ocr-results {
  height: calc(100% - 120px);
  overflow-y: auto;
  padding: 10px;
}

.scrollable {
  overflow-y: auto;
}

.image-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.image-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.calligraphy-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}

:deep(.el-image) {
  width: 100%;
  height: 100%;
}

:deep(.el-image__inner) {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.right-panel .panel-content {
  padding: 10px 40px 10px 10px;
  background: transparent;
  box-shadow: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.character-item {
  margin-bottom: 15px;
  padding: 5px;
  border-radius: 12px;
  width: 90px;
  margin: 10px;
  background: white;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  transition: all 0.2s ease;
  position: relative;
}

.character-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.15);
}

.character-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.character-label {
  font-size: 14px;
  color: #909399;
  text-align: center;
}

.character-box-wrapper {
  width: 80px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.2s ease;
  background-color: #fff;
}

.character-box-wrapper:hover {
  background-color: rgba(64, 158, 255, 0.1);
}

.modify-options {
  display: flex;
  gap: 4px;
  margin-top: 4px;
}

.choice-box {
  width: 22px;
  height: 22px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: #909399;
  background-color: #f5f7fa;
  transition: all 0.2s ease;
  cursor: pointer;
}

.choice-box:hover {
  background-color: #ecf5ff;
  color: #409EFF;
  border-color: #409EFF;
}

/* 输入框样式 */
.choice-box:deep(.el-input__wrapper) {
  padding: 0 !important;
  background-color: transparent;
  box-shadow: none !important;
  border: none;
}

.choice-box:deep(.el-input__inner) {
  height: 22px;
  padding: 0 !important;
  text-align: center;
  font-size: 12px;
  color: #909399;
  background-color: transparent;
}

.scrollable {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

.scrollable::-webkit-scrollbar {
  display: none;
}

.result-header {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
  margin: 16px 0;
  padding-left: 10px;
  border-left: 4px solid #409EFF;
}

.result-item {
  padding: 12px;
  border-bottom: 1px solid #EBEEF5;
  color: #606266;
  line-height: 1.5;
  cursor: pointer;  /* 添加鼠标指针样式 */
  transition: background-color 0.2s ease;  /* 添加过渡效果 */
}

.result-item:hover {
  background-color: #f5f7fa;  /* 添加悬停背景色 */
}

.result-item:last-child {
  border-bottom: none;
}

.highlight-overlay {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 1;
}

/* 自定义加载样式 */
:deep(.el-loading-mask) {
  background-color: rgba(255, 255, 255, 0.8);
}

:deep(.el-loading-text) {
  color: #409EFF;
  font-size: 14px;
  margin-top: 8px;
}

.choices-container {
  position: absolute;
  right: -30px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.character-item:hover .choices-container {
  opacity: 1;
}

.choice-box {
  width: 22px;
  height: 22px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: #909399;
  background-color: #f5f7fa;
  transition: all 0.2s ease;
}

.choice-box:hover {
  background-color: #ecf5ff;
  color: #409EFF;
  border-color: #409EFF;
}

/* 输入框特殊样式覆盖 */
.choice-box:deep(.el-input__wrapper) {
  padding: 0 !important;
  background-color: transparent;
  box-shadow: none !important;
  border: none;
}

.choice-box:deep(.el-input__inner) {
  height: 22px;
  padding: 0 !important;
  text-align: center;
  font-size: 12px;
  color: #909399;
  background-color: transparent;
}

/* 移除之前的自定义输入框样式 */
.custom-choice,
.custom-choice :deep(.el-input__wrapper),
.custom-choice :deep(.el-input__inner) {
  /* 移除之前的样式 */
}

.choice-box.clickable {
  cursor: pointer;
  user-select: none;
}

.choice-box.clickable:hover {
  background-color: #ecf5ff;
  color: #409EFF;
  border-color: #409EFF;
}

/* 确保输入框和可点击框样式一致 */
.choice-box:deep(.el-input__wrapper) {
  padding: 0 !important;
  background-color: transparent;
  box-shadow: none !important;
  border: none;
}

.choice-box:deep(.el-input__inner) {
  height: 22px;
  padding: 0 !important;
  text-align: center;
  font-size: 12px;
  color: #909399;
  background-color: transparent;
}

.character-box {
  transform-origin: center;
  background-position: center;
  background-repeat: no-repeat;
  background-size: auto;
  flex-shrink: 0;
}
</style>